﻿#include "utility.h"

/**
 * @brief Utility::BCC 异或校验，对传入的字节数组进行异或，得出校验值
 * @param order 传入的字节数组
 * @param len 需要校验的长度
 * @return 校验值
 */
char Utility::BCC( const QByteArray& order, int len ) {
    char bcc = 0x00;

    for ( int i = 0; i <= len; i++ ) {
        bcc ^= order.at( i );
    }
    return bcc;
}

/**
 * @brief Utility::BCC 异或校验，对传入的字节数组进行异或，得出校验值
 * @param order 传入的字节数组
 * @param start 起始的index
 * @param len 需要校验的长度
 * @return 校验值
 */
char Utility::BCC( const QByteArray& order, int start, int len ) {
    char bcc = 0x00;

    for ( int i = start; i < start + len; i++ ) {
        bcc ^= order.at( i );
    }
    return bcc;
}

/**
 * @brief Utility::CKS 和校验，对传入的字节数组进行相加，溢出部分去掉，只保留最低位字节
 * @param order 传入的字节数组
 * @param len 校验的长度
 * @return 校验值
 */
uchar Utility::CKS( const QByteArray& order, int len ) {
    uchar result = 0x00;

    for ( int i = 0; i < len; i++ ) {
        result += order.at( i );
    }
    return result;
}

/**
 * @brief Utility::CKS4TL740D 和校验，对传入的字节数组进行相加，溢出部分去掉，只保留最低位字节
 * @param order 传入的字节数组
 * @param start 开始的index
 * @param len 校验的长度
 * @return 校验值
 */
uchar Utility::CKS( const QByteArray& order, int start, int len ) {
    uchar crc = 0;

    for ( int i = start; i < start + len; i++ ) {
        crc += order.at( i );
    }
    return crc;
}

/**
 * @brief Utility::CRC16_ModBus CRC16位校验
 * @param order 传入的字节数组
 * @param num 开始的index
 * @return 校验值
 */
QByteArray Utility::CRC16_ModBus( const QByteArray& order, int num ) {
    quint16    crcRegistor = 0xFFFF;
    int        index       = num;
    QByteArray crc( 2, 0x00 );
    while ( num-- ) {
        crcRegistor ^= ( uchar( order.at( index - num - 1 ) ) );
        //      printf("%x ", (uchar)order.at(index - num - 1));
        //      crcRegistor ^= (order.at(index-num-1) & 0xFF);
        for ( qint8 i = 0; i < 8; i++ ) {
            if ( crcRegistor & 1 ) {
                crcRegistor = ( crcRegistor >> 1 ) ^ 0xA001;  //串口数据传输时低位在前，高位在后，8005应该倒过来读，就是A001
            }
            else {
                crcRegistor >>= 1;
            }
        }
    }
    //   qDebug() << QString::number(crcRegistor, 16);
    crc[ 0 ] = static_cast< char >( crcRegistor );
    crc[ 1 ] = static_cast< char >( crcRegistor >> 8 );
    return crc;
}

QByteArray Utility::CRC16_X25( const QByteArray& order, int num ) {
    quint16    crcRegistor = 0xFFFF;
    int        index       = num;
    QByteArray crc( 2, 0x00 );

    while ( num-- ) {
        crcRegistor ^= ( uchar( order.at( index - num - 1 ) ) );
        //           printf("%x ",(uchar)order.at(index-num-1));
        //        crcRegistor ^= (order.at(index-num-1) & 0xFF);
        for ( qint8 i = 0; i < 8; i++ ) {
            if ( crcRegistor & 1 ) {
                crcRegistor = ( crcRegistor >> 1 ) ^ 0x8408;  //串口数据传输时低位在前，高位在后，8005应该倒过来读，就是A001
            }
            else {
                crcRegistor >>= 1;
            }
        }
    }

    crcRegistor ^= 0xFFFF;
    //       qDebug()<<QString::number(crcRegistor,16);
    crc[ 0 ] = static_cast< char >( crcRegistor );
    crc[ 1 ] = static_cast< char >( crcRegistor >> 8 );
    return crc;
}

QString Utility::QbyteArry2Qstring( const QByteArray& data ) {
    QString strDisplay;
    QString str = data.toHex().data();

    str = str.toUpper();
    for ( int i = 0; i < str.length(); i += 2 ) {
        QString st = str.mid( i, 2 );
        strDisplay += st;
        strDisplay += " ";
    }
    return strDisplay;
}

Utility::Utility() = default;
